﻿// owner 蒋家伟

#include "ObjectClassDefine.h"

// jsdk
#include "Dbg_Warn_Define.h"
#include "ObjectReflectDefine.h"
#include "CommonFieldDescriptor.h"
#include "IDocument.h"
#include "IGenericElement.h"

using namespace std;
using namespace jsdk;

OBJECT_REFLECT_DEFINE(jsdk, TestA): m_IntTest(0), m_StrTest(L"TestA")
{
}

bool jsdk::TestA::operator==(const ITestA& testA) const
{
    return testA.getTestInt() == this->getTestInt() && testA.getTestString() == this->getTestString() && testA.getEnumTest() == this->getEnumTest();
}

OBJECT_REFLECT_DEFINE(jsdk, TestA2) : m_IntTest(2), m_Int16Test(1), m_StrTest(L"TestA2")
{
}

bool jsdk::TestA2::operator==(const ITestA& testA) const
{
    return testA.getTestInt() == this->getTestInt() && testA.getTestString() == this->getTestString() && testA.getEnumTest() == this->getEnumTest();
}

OBJECT_REFLECT_DEFINE(jsdk, TestB):m_IntTest(1), m_StrTest(L"TestB")
{
}

bool jsdk::TestB::operator==(const TestB& testB) const
{
    bool equal = true;

    int a = this->getTestInt();
    int b = testB.getTestInt();
    equal &= a == b;
    std::wstring str1 = this->getTestString();
    std::wstring str2 = testB.getTestString();
    equal &= str1 == str2;
    ElementId id1 = this->getelementId__();
    ElementId id2 = testB.getelementId__();
    equal &= id1 == id2;

    equal &= this->getFloatTest() == testB.getFloatTest();

    const OwnerPtr<ITestA>& opA2_this = this->getopTestA2Test();
    const OwnerPtr<ITestA>& opA2_testB = testB.getopTestA2Test();
    if (opA2_testB == nullptr && opA2_this == nullptr)
    {
    }
    else if (opA2_testB && opA2_this)
    {
        equal &= *opA2_testB == *opA2_this;
    }
    else
    {
        return false;
    }

    const OwnerPtr<ITestA>& opA1_this = this->getopITestATest();
    const OwnerPtr<ITestA>& opA1_testB = testB.getopITestATest();
    if (opA1_this && opA1_testB)
    {
        equal &= *opA1_this == *opA1_testB;
    }
    else if (opA1_this == nullptr && opA1_testB == nullptr)
    {

    }
    else
    {
        return false;
    }

    const OwnerPtr<TestA>& opA_this = this->getopTestATest();
    const OwnerPtr<TestA>& opA_testB = testB.getopTestATest();
    if (opA_this && opA_testB)
    {
        equal &= *opA_this == *opA_testB;
    }
    else if (opA_this == nullptr && opA_testB == nullptr)
    {
    }
    else
    {
        return false;
    }

    return equal;
}

OBJECT_REFLECT_DEFINE(jsdk, TestVectorBaseType)
{
}

bool jsdk::TestVectorBaseType::operator==(const TestVectorBaseType& vector)
{
    if (this->getDbVectorStr().size() != vector.getDbVectorStr().size())
    {
        return false;
    }
    else
    {
        const std::vector<std::string>& this_vector = this->getDbVectorStr();
        const std::vector<std::string>& target_vector = vector.getDbVectorStr();

        for (int i = 0; i < this_vector.size(); i++)
        {
            if (this_vector[i] != target_vector[i])
            {
                return false;
            }
        }
    }
    return true;
}

OBJECT_REFLECT_DEFINE(jsdk, TestVectorOwnerPtr)
{
}

bool jsdk::TestVectorOwnerPtr::operator==(const TestVectorOwnerPtr& vector) const
{
    if (this->getDbVectorTestA().size() != vector.getDbVectorTestA().size())
    {
        return false;
    }
    else
    {
        const std::vector<OwnerPtr<TestA>>& this_vector = this->getDbVectorTestA();
        const std::vector<OwnerPtr<TestA>>& target_vector = vector.getDbVectorTestA();

        for (int i = 0; i < this_vector.size(); i++)
        {
            if(this_vector[i] == nullptr && target_vector[i] == nullptr)
                continue;
            else if (this_vector[i] == nullptr || target_vector[i] == nullptr)
            {
                return false;
            }
            else
            {
                if (!(*this_vector[i] == *target_vector[i]))
                {
                    return false;
                }
            }
        }
    }

    if (this->getDbVectorITestA().size() != vector.getDbVectorITestA().size())
    {
        return false;
    }
    else
    {
        const std::vector<OwnerPtr<ITestA>>& this_vector = this->getDbVectorITestA();
        const std::vector<OwnerPtr<ITestA>>& target_vector = vector.getDbVectorITestA();

        for (int i = 0; i < this_vector.size(); i++)
        {
            if (this_vector[i] == nullptr && target_vector[i] == nullptr)
                continue;
            else if (this_vector[i] == nullptr || target_vector[i] == nullptr)
            {
                return false;
            }
            else
            {
                if (!(*this_vector[i] == *target_vector[i]))
                {
                    return false;
                }
            }
        }
    }

    if (this->getDbVectorTestB().size() != vector.getDbVectorTestB().size())
    {
        return false;
    }
    else
    {
        const std::vector<OwnerPtr<TestB>>& this_vector = this->getDbVectorTestB();
        const std::vector<OwnerPtr<TestB>>& target_vector = vector.getDbVectorTestB();

        for (int i = 0; i < this_vector.size(); i++)
        {
            if (this_vector[i] == nullptr && target_vector[i] == nullptr)
                continue;
            else if (this_vector[i] == nullptr || target_vector[i] == nullptr)
            {
                return false;
            }
            else
            {
                if (!(*this_vector[i] == *target_vector[i]))
                {
                    return false;
                }
            }
        }
    }

    return true;
}

OBJECT_REFLECT_DEFINE(jsdk, TestSetBaseType)
{
}

bool jsdk::TestSetBaseType::operator==(const TestSetBaseType& set) const
{
    {
        // 1、先比较普通的string
        const std::set<std::wstring>& this_SetStr = this->getDbSetStr__();
        const std::set<std::wstring>& target_SetStr = set.getDbSetStr__();
        if (this_SetStr.size() != target_SetStr.size())
        {
            return false;
        }
        for(auto iter_this = this_SetStr.begin(), iter_target = target_SetStr.begin(); iter_this!= this_SetStr.end() && iter_target!= target_SetStr.end(); iter_this++, iter_target++)
        { 
            if (*iter_target != *iter_this)
            {
                return false;
            }
        }
    }

    {
        // 1、在比较ownerptr
        const std::set<OwnerPtr<TestA>, OwnerPtrTestACP>& this_SetTestA = this->getDbSetTestA__();
        const std::set<OwnerPtr<TestA>, OwnerPtrTestACP>& target_SetTestA = set.getDbSetTestA__();
        if (this_SetTestA.size() != target_SetTestA.size())
        {
            return false;
        }
        for (auto iter_this = this_SetTestA.begin(), iter_target = target_SetTestA.begin(); iter_this != this_SetTestA.end() && iter_target != target_SetTestA.end(); iter_this++, iter_target++)
        {
            if (*iter_target != *iter_this)
            {
                return false;
            }
        }
    }

    return true;
}

OBJECT_REFLECT_DEFINE(jsdk, TestMap)
{
}

bool jsdk::TestMap::operator==(const TestMap& map) const
{
    {
        // 1、比较的StringToTestAMap
        const std::map<std::wstring, OwnerPtr<TestA>>& this_StringToTestAMap = this->getStringToTestAMap__();
        const std::map<std::wstring, OwnerPtr<TestA>>& target_StringToTestAMap = map.getStringToTestAMap__();
        if (this_StringToTestAMap.size() != target_StringToTestAMap.size())
        {
            return false;
        }
        for (auto iter_this = this_StringToTestAMap.begin(), iter_target = target_StringToTestAMap.begin(); iter_this != this_StringToTestAMap.end() && iter_target != target_StringToTestAMap.end(); iter_this++, iter_target++)
        {
            if (iter_target->first != iter_this->first)
            {
                return false;
            }
            if (!(*iter_target->second == *iter_this->second))
            {
                return false;
            }
        }
    }

    {
        // 2、比较IntToStringMap
        const std::map<int32_t, std::string>& this_IntToStringMap = this->getIntToStringMap__();
        const std::map<int32_t, std::string>& target_IntToStringMap = map.getIntToStringMap__();
        if (this_IntToStringMap.size() != target_IntToStringMap.size())
        {
            return false;
        }
        for (auto iter_this = this_IntToStringMap.begin(), iter_target = target_IntToStringMap.begin(); iter_this != this_IntToStringMap.end() && iter_target != target_IntToStringMap.end(); iter_this++, iter_target++)
        {
            if (iter_target->first != iter_this->first)
            {
                return false;
            }
            if (iter_target->second != iter_this->second)
            {
                return false;
            }
        }
    }

    {
        // 3、 比较StringToTestUMap
        const std::unordered_map<std::wstring, OwnerPtr<TestA>>& this_StringToTestAMap = this->getStringToTestUMap__();
        const std::unordered_map<std::wstring, OwnerPtr<TestA>>& target_StringToTestAMap = map.getStringToTestUMap__();
        if (this_StringToTestAMap.size() != target_StringToTestAMap.size())
        {
            return false;
        }
        for (auto iter_this = this_StringToTestAMap.begin(); iter_this != this_StringToTestAMap.end() ; iter_this++)
        {
            const auto& iter = target_StringToTestAMap.find(iter_this->first);
            if (iter == target_StringToTestAMap.end())
                return false;
            if (!(*iter->second == *iter_this->second))
            {
                return false;
            }
        }
    }

    {
        // 4、比较IntToStringUMap
        const std::unordered_map<int32_t, std::string>& this_IntToStringMap = this->getIntToStringUMap__();
        const std::unordered_map<int32_t, std::string>& target_IntToStringMap = map.getIntToStringUMap__();
        if (this_IntToStringMap.size() != target_IntToStringMap.size())
        {
            return false;
        }
        for (auto iter_this = this_IntToStringMap.begin(); iter_this != this_IntToStringMap.end(); iter_this++)
        {
            const auto& iter = target_IntToStringMap.find(iter_this->first);
            if (iter == target_IntToStringMap.end())
                return false;
            if (iter->second != iter_this->second)
            {
                return false;
            }
        }
    }
    return true;
}

jsdk::IElement* jsdk::Person::create(const PersonInput& input)
{
    return nullptr;
}

jsdk::Person* jsdk::Person::getFw(IDocument* pDoc, const ElementId& id)
{
    if (IGenericElement* pGenericElement = quick_cast<IGenericElement>(pDoc->getElement(id)))
    {
        if (Person* pPerson = quick_cast<Person>(pGenericElement->getExternalData()))
        {
            return pPerson;
        }
    }
    return nullptr;
}

void jsdk::Person::addFriendId(const ElementId& friendId)
{
    const auto& iter = getfriends__().find(friendId);
    if (iter != getfriends__().end())
    {
        return;
    }
    getfriendsFW__().insert(friendId);
}

void jsdk::Person::deleteFriendId(const ElementId& friendId)
{
    const auto& iter = getfriends__().find(friendId);
    if (iter == getfriends__().end())
    {
        return;
    }
    getfriendsFW__().erase(friendId);
}

const Person * Person::get(const IDocument * pDoc, const ElementId & id)
{
    if (const IGenericElement* pGenericElement = quick_cast<IGenericElement>(pDoc->getElement(id)))
    {
        if (const Person* pPerson = quick_cast<Person>(pGenericElement->getExternalData()))
        {
            return pPerson;
        }
    }
    return nullptr;
}

jsdk::IElement* jsdk::God::create(const GodInput& input)
{
    return nullptr;
}

God * God::getFw(IDocument * pDoc, const ElementId & id)
{
    return nullptr;
}

const God * God::get(const IDocument * pDoc, const ElementId & id)
{
    return nullptr;
}
